package com.jade.bss.base.account.impl;

import java.util.Date;
import java.util.List;
import javax.ejb.TransactionAttribute;
import javax.inject.Inject;
import javax.inject.Named;

import com.jade.bss.base.BssException;
import com.jade.bss.base.account.Account;
import com.jade.bss.base.account.AccountDao;
import com.jade.bss.base.account.AccountManager;
import com.jade.bss.base.account.AccountRecord;
import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.util.PagingList;
import org.springframework.transaction.annotation.Transactional;

/**
 * 账户管理器实现。
 *
 * @author dwzhang
 * @version 1.0 12-04-22 下午9:51
 */
@Named ("bss_accountManager")
public class AccountManagerImpl
        implements AccountManager
{
    protected AccountDao accountDao;

    @Inject
    public void setAccountDao(@Named ("bss_accountDao") AccountDao accountDao)
    {
        this.accountDao = accountDao;
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void createAccount(Account account)
            throws BssException
    {
        if (getAccount(account.getOwnerType(), account.getOwnerId(), account.getType()) != null) {
            throw new BssException("err.bss.account.not_existed", null, account.getOwnerType(), account.getOwnerId(),
                    account.getType());
        }
        accountDao.addAccount(account);
    }

    public Account getAccount(String ownerType, String ownerId, String type)
    {
        return accountDao.getAccount(ownerType, ownerId, type);
    }

    public Account getAccount(long id)
    {
        return accountDao.getAccount(id);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void updateAccount(Account account)
            throws BssException
    {
        Account oldAccount = getAccount(account.getId());
        if (oldAccount == null) {
            throw new BssException("err.bss.core.account_not_existed", null, account.getId());
        }
        oldAccount.setName(account.getName());
        oldAccount.setType(account.getType());
        accountDao.updateAccount(oldAccount);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void resetAccount(long id, long remnant, long prepay, long freeze)
            throws BssException
    {
        Account account = checkAccount(id);
        resetAccount(account, remnant, prepay, freeze);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void resetAccount(String ownerType, String ownerId, String type, long remnant, long prepay, long freeze)
            throws BssException
    {
        Account account = checkAccount(ownerType, ownerId, type);
        resetAccount(account, remnant, prepay, freeze);
    }

    protected void resetAccount(Account account, long remnant, long prepay, long freeze)
            throws BssException
    {
        Date opDate = new Date();
        if (remnant >= 0) {
            account.setRemnant(remnant);
            AccountRecord record = createRecord(account, "reset_remnant");
            record.setOpDate(opDate);
            record.setAmount(remnant);
            accountDao.addAccountRecord(record);
        }
        if (prepay >= 0) {
            account.setPrepay(prepay);
            AccountRecord record = createRecord(account, "reset_prepay");
            record.setOpDate(opDate);
            record.setAmount(prepay);
            accountDao.addAccountRecord(record);
        }
        if (freeze >= 0) {
            account.setFreeze(freeze);
            AccountRecord record = createRecord(account, "reset_freeze");
            record.setOpDate(opDate);
            record.setAmount(freeze);
            accountDao.addAccountRecord(record);
        }
        accountDao.updateAccount(account);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void updateAccount(Account account, long remnant, long prepay, long freeze)
            throws BssException
    {
        accountDao.updateAccount(account, remnant, prepay, freeze);
    }

    public List<Account> listAccount(String ownerType, String ownerId)
    {
        return accountDao.listAccount(ownerType, ownerId);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void removeAccount(long id)
            throws BssException
    {
        accountDao.removeAccount(id);
    }

    @TransactionAttribute
    public void removeAccount(String ownerType, String ownerId, String type)
            throws BssException
    {
        accountDao.removeAccount(ownerType, ownerId, type);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void removeAllAccount(String ownerType, String ownerId)
            throws BssException
    {
        accountDao.removeAllAccount(ownerType, ownerId);
    }

    protected Account checkAccount(String ownerType, String ownerId, String accountType)
            throws BssException
    {
        Account account = accountDao.getAccount(ownerType, ownerId, accountType);
        if (account == null) {
            throw new BssException("err.bss.account.not_existed", null, ownerType, ownerId, accountType);
        }
        return account;
    }

    protected Account checkAccount(long id)
            throws BssException
    {
        Account account = accountDao.getAccount(id);
        if (account == null) {
            throw new BssException("err.bss.account.not_existed", null, id);
        }
        return account;
    }

    protected AccountRecord createRecord(Account account, String op)
    {
        AccountRecord record = new AccountRecord();
        record.setAccountId(account.getId());
        record.setOwnerType(account.getOwnerType());
        record.setOwnerId(account.getOwnerId());
        record.setType(account.getType());
        record.setOp(op);
        record.setOpDate(new Date());
        return record;
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void recharge(long accountId, long amount, long fee)
            throws BssException
    {
        Account account = checkAccount(accountId);
        accountDao.updateAccount(account, amount, 0, 0);
        AccountRecord record = createRecord(account, "recharge");
        record.setAmount(amount);
        record.setFee(fee);
        accountDao.addAccountRecord(record);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void recharge(String ownerType, String ownerId, String accountType, long amount, long fee)
            throws BssException
    {
        Account account = checkAccount(ownerType, ownerId, accountType);
        accountDao.updateAccount(account, amount, 0, 0);
        AccountRecord record = createRecord(account, "recharge");
        record.setAmount(amount);
        record.setFee(fee);
        accountDao.addAccountRecord(record);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void freeze(String ownerType, String ownerId, String accountType, long amount)
            throws BssException
    {
        Account account = checkAccount(ownerType, ownerId, accountType);
        accountDao.updateAccount(account, -amount, 0, amount);
        AccountRecord record = createRecord(account, "freeze");
        record.setAmount(amount);
        accountDao.addAccountRecord(record);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void freeze(long accountId, long amount)
            throws BssException
    {
        Account account = checkAccount(accountId);
        accountDao.updateAccount(account, -amount, 0, amount);
        AccountRecord record = createRecord(account, "freeze");
        record.setAmount(amount);
        accountDao.addAccountRecord(record);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void unfreeze(long accountId, long amount)
            throws BssException
    {
        Account account = checkAccount(accountId);
        accountDao.updateAccount(account, amount, 0, -amount);
        AccountRecord record = createRecord(account, "unfreeze");
        record.setAmount(amount);
        accountDao.addAccountRecord(record);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void addAccountRecord(AccountRecord accountRecord)
            throws BssException
    {
        accountDao.addAccountRecord(accountRecord);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Throwable.class)
    public void updateAccountRecord(AccountRecord accountRecord)
            throws BssException
    {
        accountDao.updateAccountRecord(accountRecord);
    }

    public AccountRecord getAccountRecord(long recordId)
    {
        return accountDao.getAccountRecord(recordId);
    }

    public PagingList<Account> queryAccount(Criteria criteria)
    {
        return accountDao.queryAccount(criteria);
    }

    public PagingList<AccountRecord> queryAccountRecord(Criteria criteria)
    {
        return accountDao.queryAccountRecord(criteria);
    }
}
